# -*- coding: utf-8 -*-
# @Time     : 2021/10/8 13:41
# @Author   : JustFly
# @File     : main.py
# @Software : PyCharm
import time
import pygame
import random
from pygame.locals import *
from sys import exit

# 尺寸
SCREEN_WIDTH = 480
SCREEN_HEIGHT = 700
# 难度
GAME_LEVEL = 1

PLAYER_SPEED = 8
BULLET_SPEED = 10
BULLET_DENSITY = 10
ENEMY_SPEED = 2
ENEMY_DENSITY = 3


# 子弹类
class Bullet(pygame.sprite.Sprite):
    def __init__(self, bullet_img, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = bullet_img
        self.rect = self.image.get_rect()
        self.rect.midbottom = init_pos
        self.speed = BULLET_SPEED

    def move(self):
        self.rect.top -= self.speed

# NPC
class Enemy(pygame.sprite.Sprite):
    def __init__(self, enemy_img, enemy_down_imgs, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = enemy_img
        self.rect = self.image.get_rect()
        self.rect.topleft = init_pos
        self.down_imgs = enemy_down_imgs
        self.speed = ENEMY_SPEED
        self.down_index = 0

    def move(self):
        self.rect.top += self.speed


# 玩家
class Player(pygame.sprite.Sprite):
    def __init__(self, plane_img, player_rect, init_pos):
        pygame.sprite.Sprite.__init__(self)
        self.image = plane_img
        # for i in range(len(player_rect)):
        #     self.image.append(plane_img.subsurface(player_rect[i]).convert_alpha())
        self.rect = player_rect[0]  # 矩形对象
        self.rect.topleft = init_pos
        self.speed = PLAYER_SPEED
        self.bullets = pygame.sprite.Group()
        self.image_index = 0
        self.is_hit = False

    # 发射子弹
    def shoot(self, bullet_img):
        bullet = Bullet(bullet_img, self.rect.midbottom)
        self.bullets.add(bullet)
    # 发射子弹
    def shootl(self, bullet_img):
        bullet = Bullet(bullet_img, self.rect.midleft)
        self.bullets.add(bullet)
    # 发射子弹
    def shootr(self, bullet_img):
        bullet = Bullet(bullet_img, self.rect.midright)
        self.bullets.add(bullet)


    # 向上移动   left/top 即据左/上距离 right/bottom 距左/上距离加本身宽/高
    def moveUp(self):
        if self.rect.top <= 0:
            self.rect.top = 0
        else:
            self.rect.top -= self.speed

    # 向下
    def moveDown(self):
        if self.rect.bottom >= SCREEN_HEIGHT:
            self.rect.bottom = SCREEN_HEIGHT
        else:
            self.rect.bottom += self.speed

    # 向左
    def moveLeft(self):
        if self.rect.left <= 0:
            self.rect.left = 0
        else:
            self.rect.left -= self.speed

    # 向右
    def moveRight(self):
        if self.rect.right >= SCREEN_WIDTH:
            self.rect.right = SCREEN_WIDTH
        else:
            self.rect.right += self.speed

# 保存游戏分数
def get_rank(score):


    REFRESH = False  # 是否破排行纪录
    SCORE = score
    DATESTR = time.strftime("DATE: %Y-%m-%d %H:%M:%S SCORE: ", time.localtime())

    # 读取排行
    with open("./rank.txt", "r") as f:
        rankstr = f.readline().split("-")
        rankint = list(map(int, rankstr))  # [int(x) for x in rankstr]
        if SCORE > rankint[-1]:
            rankint.append(SCORE)
            rankint.sort(reverse=True)
            RANKSTR = "-".join(list(map(str, rankint[:10])))
            # 存储排行
            with open("./rank.txt", "w") as f:
                f.write(RANKSTR)
                f.close()
            REFRESH = True

    # 保存日志
    with open(r"./log.txt", "a") as f:
        f.write("REFRESH: %s " % str(REFRESH) + DATESTR + str(SCORE) + "\n")
        f.close()

    return REFRESH, rankint


# 开始游戏
def start_game():
    # 初始化参数
    GAME_LEVEL = 1

    PLAYER_SPEED = 8
    BULLET_SPEED = 10
    BULLET_DENSITY = 10
    ENEMY_SPEED = 2
    ENEMY_DENSITY = 3
    # NPC 组
    enemies = pygame.sprite.Group()
    enemies_down = pygame.sprite.Group()
    # 玩家 初始位置
    player_pos = [SCREEN_WIDTH / 2, SCREEN_HEIGHT - 100]
    player = Player(plane_imgs, player_rect, player_pos)
    #  游戏主循环
    PLAYER_SCORE = 0
    running = True
    bullet_frequent = 0
    enemy1_frequent = 0
    player_down_index = 2
    clock = pygame.time.Clock()

    while running:
        #clock.tick(90)  # 游戏绘制的最大帧率

        screen.fill(0)  # 填充底色
        screen.blit(background, (0, 0))
        #  生成子弹

        if not player.is_hit:
            bullet_frequent += BULLET_DENSITY
            if bullet_frequent % 100 == 0 or bullet_frequent > 100:
                if GAME_LEVEL <= 15:
                    if GAME_LEVEL < 3:
                        player.shoot(bullet_img)
                    elif GAME_LEVEL < 6:
                        player.shootr(bullet_img)
                        player.shootl(bullet_img)
                    elif GAME_LEVEL < 9:
                        player.shoot(bullet_img)
                        player.shootr(bullet_img)
                        player.shootl(bullet_img)
                    elif GAME_LEVEL <= 15:
                        player.shoot(bullet_img)
                        player.shootr(bullet_img2)
                        player.shootl(bullet_img2)

                else:
                    if 15 < GAME_LEVEL < 25:
                        player.shoot(bullet_img2)
                        player.shootr(bullet_img2)
                        player.shootl(bullet_img2)
                    elif 25 < GAME_LEVEL < 35:
                        if GAME_LEVEL % 26 == 0:
                            BULLET_DENSITY = 30
                        player.shoot(bullet_img3)
                        player.shootr(bullet_img2)
                        player.shootl(bullet_img2)
                    elif GAME_LEVEL < 60:
                        if GAME_LEVEL % 37 == 0:
                            BULLET_DENSITY = 30
                        player.shoot(bullet_img2)
                        player.shootr(bullet_img3)
                        player.shootl(bullet_img3)
                    else:
                        if GAME_LEVEL % 61 == 0:
                            BULLET_DENSITY = 30
                        player.shoot(bullet_img3)
                        player.shootr(bullet_img3)
                        player.shootl(bullet_img3)
                bullet_frequent = 0
        for bullet in player.bullets:
            bullet.move()
            if bullet.rect.bottom > SCREEN_HEIGHT:
                player.bullets.remove(bullet)
        player.bullets.draw(screen)

        # NPC
        enemy1_frequent += ENEMY_DENSITY
        if enemy1_frequent % 100 == 0 or enemy1_frequent > 100:
            enemy1_pos = [random.randint(0, SCREEN_WIDTH - enemy1_rect.width), 0]
            enemy1 = Enemy(enemy1_img, enemy1_down_imgs, enemy1_pos)
            enemies.add(enemy1)
            enemy1_frequent = 0
        for enemy in enemies:
            enemy.move()

            if enemy.rect.top < 0:
                enemies.remove(enemy)
            if pygame.sprite.collide_circle(enemy, player):  # 玩家与NPC是否碰撞
                enemies_down.add(enemy)
                enemies.remove(enemy)
                player.is_hit = True
                break

        #  玩家飞机
        if not player.is_hit:
            screen.blit(player.image[player.image_index], player.rect)
            player.image_index = bullet_frequent % 2
        else:
            player.image_index = player_down_index // 9
            screen.blit(player.image[player.image_index], player.rect)
            player_down_index += 1
            if player_down_index > 50:    # 刷新50次后再退出
                running = False
        # kay, value
        enemies1_down = pygame.sprite.groupcollide(enemies, player.bullets, True, 1)  # 存放被射击的NPC

        # 处理 碰到子弹的 NPC

        for enemy_down in enemies1_down:    # 回收被击落的类型1 NPC
             enemies_down.add(enemy_down)
        for enemy_down in enemies_down:
            if enemy_down.down_index > 32:
                enemies_down.remove(enemy_down)
                PLAYER_SCORE += (SCREEN_HEIGHT - player.rect.bottom) // 25 + 2  # 越靠近顶部 得分越高
                #PLAYER_SCORE += 1
                continue
            screen.blit(enemy_down.down_imgs[enemy_down.down_index // 11], enemy_down.rect)
            enemy_down.down_index += 1
        enemies.draw(screen)
        # 展示分数
        score_font = pygame.font.Font(None, 36)
        score_text = score_font.render("Score:" + str(int(PLAYER_SCORE)), True, (128, 128, 128))
        text_rect = score_text.get_rect()
        screen.blit(score_text, text_rect)
        # 战机坐标 和得分
        score_font = pygame.font.Font(None, 25)
        score_text = score_font.render("Buff ! +%d" % ((SCREEN_HEIGHT - player.rect.bottom) // 25), True, (128, 128, 128))
        text_rect = score_text.get_rect()
        text_rect.centery = SCREEN_HEIGHT - 20
        screen.blit(score_text, text_rect)
        # 当前难度等级
        level_font = pygame.font.Font(None, 36)
        level_text = level_font.render("Level:%s" % str(GAME_LEVEL), True, (128, 128, 128))
        level_rect = level_text.get_rect()
        level_rect.centerx = SCREEN_WIDTH - 80
        screen.blit(level_text, level_rect)

        pygame.display.update()


        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()

        # 难度提升

        if PLAYER_SCORE > GAME_LEVEL*100:
            #print(ENEMY_DENSITY, PLAYER_SPEED, BULLET_DENSITY, BULLET_SPEED, GAME_LEVEL)
            PLAYER_SPEED += 0.1
            BULLET_SPEED += 1
            BULLET_DENSITY += 2
            #ENEMY_SPEED += 0.1
            ENEMY_DENSITY += 1
            GAME_LEVEL += 1
        # 玩家控制
        key_pressed = pygame.key.get_pressed()

        # up
        if key_pressed[K_w] or key_pressed[K_UP]:
            player.moveUp()
        # down
        if key_pressed[K_s] or key_pressed[K_DOWN]:
            player.moveDown()
        # left
        if key_pressed[K_a] or key_pressed[K_LEFT]:
            player.moveLeft()
        # right
        if key_pressed[K_d] or key_pressed[K_RIGHT]:
            player.moveRight()
    # 计算排行
    refresh, ranklist = get_rank(PLAYER_SCORE)
    # 结束画面
    screen.blit(gameover, (SCREEN_WIDTH / 5, SCREEN_HEIGHT*4 / 5))
    screen.blit(regame, (SCREEN_WIDTH / 5, SCREEN_HEIGHT*9 / 10))
    # 分数
    #font = pygame.font.Font(None, 80)
    xtfont = pygame.font.SysFont('SimHei', 30)
    text = xtfont.render('刷新排行:%s ' % str(refresh) + '得分:' + str(PLAYER_SCORE), True, (245, 245, 245))
    text_rect = text.get_rect()
    text_rect.centerx = screen.get_rect().centerx
    text_rect.centery = screen.get_rect().centery / 4
    screen.blit(text, text_rect)
    # # 再来一局
    # xtfont = pygame.font.SysFont('SimHei', 30)
    # textstart = xtfont.render('再来一局', True, (245, 245, 245))
    # textstart_rect = textstart.get_rect()
    # textstart_rect.centerx = screen.get_rect().centerx
    # textstart_rect.centery = screen.get_rect().centery / 4
    # screen.blit(textstart, textstart_rect)
    # 排行榜
    textrank = xtfont.render('排行榜', True, (245, 245, 245))
    textrank_rect = textrank.get_rect()
    textrank_rect.centerx = screen.get_rect().centerx
    textrank_rect.centery = screen.get_rect().centery / 2
    screen.blit(textrank, textrank_rect)

    rkfont = pygame.font.SysFont('SimHei', 25)
    for i in range(len(ranklist)):
        rank_i = rkfont.render('第 %d 名: %d' % (i + 1, ranklist[i]), True, (128, 128, 128))
        rank_i_rect = textrank.get_rect()
        rank_i_rect.centerx = screen.get_rect().centerx - 50
        rank_i_rect.centery = screen.get_rect().centery*0.6 + 30*(i+1)
        screen.blit(rank_i, rank_i_rect)

    while True:
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                pygame.quit()
                exit()
            elif event.type == pygame.MOUSEBUTTONDOWN:
                x, y = event.pos
                if 95 < x < 395 and 630 < y < 670:  # 再来一局
                    start_game()
                elif 100 < x < 395 and 557 < y < 597:  # 结束游戏
                    pygame.quit()
                    exit()
            pygame.display.update()


# 初始化 pygame
pygame.init()
# window size
screen = pygame.display.set_mode((SCREEN_WIDTH, SCREEN_HEIGHT))
pygame.display.set_caption("JFGame")
# icon
ic_launcher = pygame.image.load('./resources/image/p.ico')
pygame.display.set_icon(ic_launcher)
# bg
background = pygame.image.load("./resources/image/bg.png")
gameover = pygame.image.load("./resources/image/gameover.png")
# regame
regame = pygame.image.load("./resources/image/regame.png")

# 玩家 子弹 NPC
player_rect = [pygame.Rect(0, 99, 100, 120), pygame.Rect(165, 360, 102, 126), pygame.Rect(165, 234, 102, 126),
               pygame.Rect(330, 498, 102, 126), pygame.Rect(432, 624, 102, 126)]
plane_imgs = [pygame.image.load("./resources/image/me1.png"), pygame.image.load("./resources/image/me2.png"),
              pygame.image.load("./resources/image/me_destroy_1.png"),
              pygame.image.load("./resources/image/me_destroy_2.png"),
              pygame.image.load("./resources/image/me_destroy_3.png"),
              pygame.image.load("./resources/image/me_destroy_4.png")]  # 玩家5中状态
# 子弹
bullet_rect = pygame.Rect(100, 987, 10, 21)
bullet_img = pygame.image.load("./resources/image/bullet1.png")

bullet_rect2 = pygame.Rect(100, 987, 10, 21)
bullet_img2 = pygame.image.load("./resources/image/bullet2.png")

bullet_rect3 = pygame.Rect(100, 987, 10, 21)
bullet_img3 = pygame.image.load("./resources/image/bomb.png")
# NPC
enemy1_rect = pygame.Rect(530, 612, 57, 43)
enemy1_img = pygame.image.load("./resources/image/enemy1.png")
# enmy1 爆炸
enemy1_down_rect = [pygame.Rect(267, 347, 57, 43), pygame.Rect(873, 697, 57, 43), pygame.Rect(267, 296, 57, 43),
                    pygame.Rect(930, 697, 57, 43)]
enemy1_down_imgs = [pygame.image.load("./resources/image/enemy1_down1.png"),
                    pygame.image.load("./resources/image/enemy1_down2.png"),
                    pygame.image.load("./resources/image/enemy1_down3.png"),
                    pygame.image.load("./resources/image/enemy1_down4.png"),]




if __name__ == '__main__':
    start_game()
